/*
mdemon.c tvori hlavny zdrojovy subor pre mdemon, pricom mdemon je viac-menej skompilovany mdemon.c
- jeho ulohou, je pripojit sa na modem mobilu(otvori si subor predstavujuci komunikacny kanal do modemu mobilu), nastavit ho tak, 
  aby bol použiteľný pre naše účely, nasledne vytvorit si server na ktorom bude počúvať prichádzajuce spojenia a vybavovat požiadavky od klientskych aplikacii. 
  Po inicializaci sameho seba, pripojeni a nastaveni mobilneho zariadenia a pripojení vlastného servra na určenú IP adresu a port, sa program daemonizuje(zacne bezat na pozadi) 
  a bude vybavovat prichadzajuce hovory(ukonci hovor a pokusi sa spustit program ktory sa ma spustit ak dane cislo zavola) a vybavovat a obsluhovat pripojenych klientov.
- program po spusteny nacita svoj konfiguracny subor mdemon.conf a users.conf podla ktorych sa inicializuje - o to sa stara funkcia int inicializuj()
  Ak sa nepodari zaciatocna inicializacia - program skonci s chybou.
  z mdemon.conf sa nacitaju udaje ktore sa ulozia do globalnych premennych:
  DEVICE <param> // <param> obsahuje cestu k seriovemu portu modemu jeho hodnota sa ulozi do globalnej premmennej char *path
  IP <param> // <param> obsahuje IP adresu na ktorej ma mdemon pocuvat prich. spojenia. ak <param> = ALL, pocuva na vsetkych adresach pocitaca, 
             //   hodnota <param> sa ulozi do globalnej premmennej char *ip_adress;
  PORT <param> // <param> obsahuje cislo portu kde ma mdemon pocuvat prich spojenia.  hodnota <param> sa ulozi do globalnej premmennej char *ip_port;
  CALLS  // predstavuje zaciatok useku venovany zoznamu cisel a programov, ktore sa maju spustit po zavolani tohto cisla na pripojeny mobil
  <tel> <path> <argumet0> ... <argumentn> // pre kazdy takyto riadok sa prida do zoznamu volania prida jeden zaznam (volanie) pozostavajuci z telefonneho cislo a programu s argumentami
  
  z users.conf sa nacitavaju prihlasovacie mena(login) a hesla uzivatelov - co riadok to jeden uzivatel - stara sa o to funkcia load_users_from_file.
  login heslo // kazdy takyto riadok sa spracuje, pricom sa do zoznamu opravnenych uzivatelov(uzivatelia) prida uzivatel s login = login a heslo = heslo

- po uspesnej inicializacii program sa pokusi o otvorenie mobilu 
   - ak bude neuspesny skonci s chybou
   - inak si do fd_mobile ulozi file descriptor mobilu
- program vysle nastavovacie at prikazy na nastavenie mobilu - zabezpecuje to funkcia int nastav_mobil() 
  ulohou nastav_mobil() je zistit 
  *ci modem reaguje a nastavit aby komunikoval vo verbalnej forme, (AT V1)
  *nastavit clip aby sa zobrazovali cisla volajucich (+clip)
  *nastavit text mode prip PDU mod pre posielanie sms(ak sa nepodari nastavit ani jeden mod mdemon skonci s chybou) (+cmfg)
  *nastavit co nejucinejsi sposob pre ukoncovanie prich. hovoroov (+chup -zisti ci sa tym da zlozit telefon ak nie bude sa na ukoncenie hovoru pouzivat ath)
  - v pripade, ze sa modem mobilu samovolne odpoji od mobilu skonci s chybou a mdemon konci
- po nastaveni mobilu program vytvori server, ktoreho file descriptor si ulozi v fd_server_socket  a pripoji sa na ip a port definovanom v mdemon.conf(ip_adress, ip_port)
  V pripade neuspechu mdemon skonci s chybou
- po uspesnom pripojeni na server sa program daemonizuje a o svojich aktivitach bude informovat pomocou syslog(to robi od spustenia programu)
- program zavola int pocuvaj() a bude pocuvat komunikaciu od mobilu, clientov a server ci sa niekto nechce pripojit. ak ano do pola clientov sa prida client.
  ak sa client odpoji - odstrani sa zo zoznamu
  klienti sa vybavuju postupne nie paralelne
  ak nejaky autorizovany client da suspend, jedine on bude moct dat resume. ak sa suspendovatel odpoji a nezavola pred tym resume, 
  hocaky iny autorizovany client bude moct dat resume. (clientovi sa odporuca ak chce poslat sms pred tym poslat resume)
  od klienta sa spracuvaju len nasledovne spravy:
  AUTH <login> <heslo>\n
  SUSPEND\n
  RESUME|n
  CLOSE\n
  SENDSMS <cislo v medzinarodnom tvare zacinajuce +, bez medzier a inych pomocnych znakov> <text najviac 160 znakov dlhy neobsahujuci "\n" pricom za dva znaky sa pocitaju znaky co patria medzi GSM7 special chars>\n
  spravy od demona maju tvar:
  <cislo_odpovede(napr 200, 400)><:textovy vyznam cisla>\n
- spravy od clientov a mobilu sa ukladaju do buffra a za cele sa povazuju ak sa 
  - v pripade mobilu koncia "ERROR\r(\n)" "OK\r(\n)" ">\r\(\n)" alebo v pripade RING so zapnutym klipom sa zobrazilo cele cislo volaneho uzavreneho "" a na konci bolo \n 
    alebo \n v pripade RING bez zapnuteho clipu
  - v pripade clienta ak konci \n
- ak z pri komunikaci z mobilom vysvitne ze sa odpojil(posle nic), mdemon sa ukonci s chybou;
- ak autorizovany klient posle CLOSE, mdemon bude ukonceny
- na vypis sprav o stave cinnostiach pouziva mdemon syslog a do zdemonizovania posiela svoj vystup aj na terminal
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/select.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/ioctl.h>

#include <syslog.h>

#include "MessageToPDUMessage.h"

#define MDEMONCONFPATH "/usr/local/etc/mdemon/mdemon.conf" 
#define MDEMONUSERSPATH "/usr/local/etc/mdemon/users.conf"

typedef struct {
  char *login;
  char *heslo;
} UZIVATEL;

typedef struct{
  char *telefon;
  char *path;
  char **arguments;
} VOLANIE;

typedef struct{
  int fd;
  int authorized;
  char *buffer;
} CLIENT;

char *path; // cesta k mobilnemu zariadeniu 
char *pin = NULL;
char *ip_adress;
char *ip_port;
UZIVATEL **uzivatelia; //databaza uzivatelov(USERS) spolu s ich hesla, ktora je opravnena robit s demonom 
int pocet_uzivatelov = 0; // vyjadruje pocet osob v databaze uzivatelov;
VOLANIE **volania; // databaza CALLS
int pocet_volani = 0;
CLIENT **clienti; //databaza clientov pripojenych k demonovi
int pocet_clientov = 0; //pocet clientov pripojenych k demonovi

int fd_mobile = -1;  // file descriptor pre mobil
int fd_server_socket = -1; // file descriptor pre server na ktory sa pripajaju klienti
int clip = 0; // vyjadruje ci je v mobile zapnuta sluzba clip (1=ano, 0=nie)
int text_mode = 0; //vyjadruje ci je v mobile zapnuty text mode
int pdu_mode = 0; //vyjadruje ci je v mobile zapnuty PDU mode
int chup = 0; // vyjadruje ci sa da ukoncit hovor pomocou +CHUP
int suspended = 0; // vyjadruje ci je demon prave odpojeny od mobilu
int fd_suspender = -1; // file descriptor clienta, ktory odpojil demona od mobilu a jedinej aplikacie ktora moze opetovne pripojit demona k mobilu 
		      //- ak sa klientska aplikacia odpoji, demona moze opatovne pripojit hociktora ina aplikacia pripojena k demonovi
char *mbuffer; // buffer prichadzajucich sprav od mobilu


int inicializuj(void); // nacita udaje z mdemon.conf a inicializuje globalne premenne potrebne na chod mdemon
int hladaj(FILE **file, char *filename, char *command, char **parameter, int *pocet_riadkov); //pomocna funkcia pre inicializuj()
int hladaj1(FILE **file, char *filename, char *command, int *pocet_riadkov); // pomocna funkcia pre inicializuj()
int load_users_from_file(char *filename); //pomocna funkcia pre inicializuj()
void pridaj_uzivatela(char *login, char *heslo); // pomocna funkcia pre load_users_from_file()
int load_volania_from_file(FILE **fvolania, char *filename); // pomocna funkcia pre inicializuj()
int nastav(char *command, char *hlaska);
int nastav_mobil(void); // nastavi mobil pre komunikaciu z mdemon
int sprav_server(char *ip, char *port); // pripoji mdemon na dany port a ip adresu
int pocuvaj(void); // funkcia obsluhujuca prichodze spojenia a spravy od mobila a pripojenych klientov

int obsluz_clienta(char *sprava_od_clienta, int fd); // stara sa o komunikaciu s klientom
int pridaj_clienta(int fd); //prida klienta to zoznamu pripojenych klientov **clienti
int odober_clienta(int fd); //odobere klienta zo zoznamu pripojenych klientov **clienti
int daj_clienta(int fd, CLIENT **client); //vrati klienta zo zoznamu pripojenych klientov podla file_descriptora klienta
void resetuj_buffer(char **buffer); // vynuluje dany buffer - vyuziva sa pri buffroch jednotlivych klientov
void pridaj_do_buffru(char **buffer, char *co); // prida spravu do daneho buffru - vyuziva sa pri buffroch jednotlivych klientov
int autorizovany_client(int fd); // funkcia vracajuca 0 pre neautorizovaneho klienta a 1 pre autorizovaneho - o akeho klienta sa jedna urci filedescriptor pripojeneho klienta

int auth(char *login, char *heslo); // sluzi na autorizaciu klienta na zaklade zoznamu opravnenych uzivatelov *uzivatelia
                                    //- vrati 0 ak sa klienta podariloo autorizovat - 1 nepodarilo 
int send_sms(char *number, char *text); // posle sms  
int send_PDUsms(char *number, char *text); // pomocna funkcia send_sms - vyvola sa v pripade ak je nastaveny PDU mod
int suspend(void); // odpoji mdemon od mobilu, avsak mdemon stale bezi a vybavuje klientov
int resume(void); // opatovne pripoji mdemon k mobilu

//int send_command(char *com); // asi zbytocna
int send_command_and_get_response(char *command, char **response); // vysle AT command mobilu a odpoved ulozi do response - moze sposobit zamrznutie mdemon (BUG a Feature v jednom)
int obsluz_mobil(char *sprava_od_mobile); //zaobera sa prichadzajucim spravami od mobilu - vacsinou RING
int vybav_volanie(char *tel); // funkcia hlada cislo volajuceho v zozname *volania a ak ho tam najde, spusti v dalsom procese program prisluchajuci k danemu cislu
int zloz_telefon(void); 
void resetuj_mbuffer(); // nastavi mbuffer na "" - vyuziva sa pri komunikaci s mobilom
void pridaj_do_mbuffru(char *co); // prida string do buffru - vyuziva sa pri komunikaci s mobilom


int main(int argc, char *argv[]){
  
  int i;
  int len = 0;  
  char *ip;
  
  // nastavi syslog pre mdemon
  openlog("mdemon", LOG_PID|LOG_CONS, LOG_USER);
  
  // inicializujeme mdemon podla mdemon.conf
  if ( inicializuj() != 0)
    return 1;
  
  /*
   * otvorime mobil aby mohol komunikovat s demonom  
   * O_RDWR - na citanie a zapis
   * O_NOCITY - this program doesn't want to be the "controlling terminal" for that port
   * O_NDELAY - flag tells UNIX that this program doesn't care what state the DCD signal line is in - whether the other end of the port is up and running. 
   *            If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.
   */ 
  fd_mobile = open( path, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK );
  if (fd_mobile == -1)
  {
    perror("open_port: Unable to open mobile device"); /* nepodarilo sa otvorit port */
    syslog(LOG_ERR, "open_port: Unable to open mobile device - %m");
    return -1;
  }
  
  /* nastavi descriptor aby po read vratil pocet vratenych bytov alebo 0 ak buffer pre input je prazdny - necaka na godota */
  fcntl(fd_mobile, F_SETFL, 0);  
 
  /* 
   *  resetujeme mbuffer - vyprazdnime a pripravime buffer na primanie sprav od mobilu(riesime tim problem, ze mobil niekedy 
   *    posiela spravy po kuskoch a buffer sluzi na to aby sme z kuskov poskladali celu spravu)  
   *  zavolame prvotne inicializacne AT commandy a nastavime si mobil pre dalsiu komunikaciu(otestujeme pripojenie, nastavime sluzbu clip a zapneme text mode na primanie SMS)
   */  
  resetuj_mbuffer();
  if ((i = nastav_mobil()) == -1)
  {
    printf("mobil sa necakane odpojil od pocitca a mdemon konci\n");
    syslog(LOG_ERR, "mobil sa necakane odpojil od pocitca a mdemon konci\n");
    return 1;
  }
  
  //printf("send_PDUsms:%d\n", send_sms("+421908123456", "Ahoj bobor"));
  
  /*
   * vytvorime socket server na porte IP adrese a porte urcenej mdemon.conf a zacneme pocuvat prichadzajuce spojenia pre server a spravy od mobilu  
   */
  if(sprav_server(ip_adress, ip_port) == 0)
  {
    printf("podarilo sa spravit server\n");
    syslog(LOG_INFO, "podarilo sa spravit server\n");
  }
  else
  {
    printf("nepodarilo sa spravit server a mdemon konci\n");
    syslog(LOG_ERR, "nepodarilo sa spravit server a mdemon konci\n");
    return -1;
  }
 
  
 /*
  * vytvorime s programu daemon - program sa odpoji od terminalu a zacne bezat na pozadi
  */
  if (daemon(0, 0) != 0)
  {
    perror("daemonizacia:");
    syslog(LOG_ERR, "damenizacia - %m");
  }
  /*
   * mdemon zacne pocuvat komunikaciu od mobilu, server ci sa niekto nechce pripojit a vybavovat pripojenych klientov  
   */
  if ((i = pocuvaj()) == -1)
  {
    syslog(LOG_ERR, "mobil sa necakane odpojil od pocitca a mdemon konci\n");
    return 1;
  }
  else if (i == 0)
  {
    syslog(LOG_ERR, "Klientska aplikacia zavolala CLOSE a mdemon konci\n");
    return 0;
  }
  else
    return 1;
  
}

/*
pomocna funkcia inicializuj()
 hladaj prehladava otvoreny subor file s menom filename od riadku definovoanom v pocet_riadkov 
 a hlada v nom riadok po riadku pikaz(command) s nastavovacim parametrom (parameter), pricom pri precitany riadku ulozi incrementuke pocet_riadkov,
 aby sme vedeli ktory riadok suboru citame.
 ak funkcia nenajde riadok tvaru command prikaz do koncu suboru, skonci s chybou a vrati 1, inak zapise najdeny parameter do premennej parameter a skonci s 0.
*/
int hladaj(FILE **file, char *filename, char *command, char **parameter, int *pocet_riadkov)
{
  int hladaj = 1;
  int line_max = 1000;
  char *kommand; 
  kommand = malloc(256*sizeof(char));
  char *riadok;
  riadok = (char *) malloc((line_max+3)*sizeof(char));
  int len = 0;
  //command = malloc(256*sizeof(char));
  (*parameter) = malloc(256*sizeof(char));

  
  while (hladaj) 
  {
    if (fgets(riadok, (line_max+3), (*file)) == NULL)
      return 1;
    
    (*pocet_riadkov)++;
    len = strlen(riadok);
    if (len > line_max){
      printf("%s: riadok %d je dlhsi ako %d znakov\n", filename, *pocet_riadkov, line_max);
      syslog(LOG_ERR, "%s: riadok %d je dlhsi ako %d znakov\n", filename, *pocet_riadkov, line_max);
      //return 1;
    }
    if (riadok[0] == '#')
    {
    }
    else if (sscanf(riadok, "%255s %255s", kommand, (*parameter)) == 2)
    {
      if (strcmp(kommand, command) == 0)
	return 0;
    }
  }
}

/*
 ako hladaj len hlada riadok iba s commandom bez parametra
*/
int hladaj1(FILE **file, char *filename, char *command, int *pocet_riadkov)
{
  int hladaj = 1;
  int line_max = 1000;
  char *kommand; 
  kommand = malloc(256*sizeof(char));
  char *riadok;
  riadok = (char *) malloc((line_max+3)*sizeof(char));
  int len = 0;
  
  while (hladaj) 
  {
    if (fgets(riadok, (line_max+3), (*file)) == NULL)
      return 1;
    
    (*pocet_riadkov)++;
    len = strlen(riadok);
    if (len > line_max){
      printf("%s: riadok %d je dlhsi ako %d znakov\n", filename, *pocet_riadkov, line_max);
      syslog(LOG_ERR, "%s: riadok %d je dlhsi ako %d znakov\n", filename, *pocet_riadkov, line_max);
    }
    if (riadok[0] == '#')
    {
    }
    else if (sscanf(riadok, "%255s", kommand) == 1)
    {
      if (strcmp(kommand, command) == 0)
	return 0;
    }
  }
}

/*
otvori MDEMONCONFPATH a postupne z neho cita riadky a hlada nastavenia, ktore musia byt uvedene v tomto poradi: DEVICE, IP, PORT, CALLS, volania.
CALLS s volaniami su nepovinne, ostatne parametre su povinne a v pripade, ze program nenajde definovany povinny parameter v spravnom poradi, inicializuj skonci s chybou.
Po uspesnom nacitani udajov z mdemon.conf zavola funkciu load_users_from_file, ktora sa stara o nacitavanie uzivatelov z MDEMONUSERSPATH
K hladaniu nastaveni vyuziva funkcie hladaj a hladaj1, ktore hladaju nastavenie resp vyrazy v mdemon.conf riadok po riadku. ak najdu co hladaju, skoncia a inicializuj 
zacne hladat od daneho miesta dalsie nastavenia. ak je nastavenie povinne a nenajde sa do konca suboru, inicializuj skonci s chybou 1
v tomto poradi a takto sa hladaju nastavenia:
device &path # (priklad path /dev/rfcomm0)
IP &ip_adress
PORT &ip_port
CALLS # nepovinne ak sa najde tak sa spusti load_volania_from_file, ktory zaznamena nastavenia pre prichadzajuce hovori 
      # a programy ake sa maju spustit pri volani daneho cisla do

inicializuj ignoruje prazdne riadky a riadky zacinajuce #, ktore predstavuju komentar
riadok suboru nesmie mat oficialne viac ako 1000 znakov - vacsi riadok sa nebude spracovat a program upozorni na chybny riadok
*/
int inicializuj(){
  
  char *filename = MDEMONCONFPATH; 
  char *usersfilename = MDEMONUSERSPATH; 
  int line_max = 1000; // riadok nesmie mat viac ako 1000 znakov oficialne
  int hladame = 1;
  int hladaj_ip = 0;
  FILE *file;
  file = fopen(filename, "r");
  if (file == NULL)
  {
    perror("mdemon.conf");
    syslog(LOG_ERR, "%s: %m\n", filename);
    return -1;
  }
    
  char *command; 
  command = malloc(256*sizeof(char));
  char *parameter;
  parameter = malloc(256*sizeof(char));
  char *riadok;
  int pocet_riadkov = 0;
  int len = 0;
  riadok = (char *) malloc((line_max+3)*sizeof(char));
  path = (char *) malloc(256*sizeof(char));
 
  // hladame device a k nemu nazov suboru (napr.: device /dev/rfcomm0)
  if (hladaj(&file, filename, "DEVICE", &path, &pocet_riadkov) != 0)
  {
    printf("%s: subor neobsahuje povinne nastavenie %s\n", filename, "DEVICE");
    syslog(LOG_ERR, "%s: subor neobsahuje povinne nastavenie %s\n", filename, "DEVICE");
    return 1;
  }
  if (hladaj(&file, filename, "IP", &ip_adress, &pocet_riadkov) != 0)
  {
    printf("%s: subor neobsahuje povinne nastavenie %s\n", filename, "IP");
    syslog(LOG_ERR, "%s: subor neobsahuje povinne nastavenie %s\n", filename, "IP");
    return 1;
  }
  if (hladaj(&file, filename, "PORT", &ip_port, &pocet_riadkov) != 0)
  {
    printf("%s: subor neobsahuje povinne nastavenie %s\n", filename, "PORT");
    syslog(LOG_ERR, "%s: subor neobsahuje povinne nastavenie %s\n", filename, "PORT");
    return 1;
  }
  
  if (hladaj1(&file, filename, "CALLS", &pocet_riadkov) == 0)
    load_volania_from_file(&file, filename);
  
  
  if (load_users_from_file(usersfilename) != 0)
    return 1;
  
  fclose(file);
  return 0;
}


/*
load_users_from_file nacita uzivatelov zo suboru danom v filename (vzdy by to mal byt MDEMONUSERSPATH)
format riadku je nasledovny:
login heslo
- login ma mat od 1-255 znakov
- helo ma mat od 1-255 znakov
- riadok nesmie mat viac ako 1023 znakov
*/
int load_users_from_file(char *filename){
  
  FILE *file;
  file = fopen(filename, "r");
  if (file == NULL)
  {
    perror("users.conf");
    syslog(LOG_ERR, "%s: %m\n", filename);
    return -1;
  }
  int pocet_riadkov = 0;
  char *login, *heslo;
  int i = 0;
  int len = 0;
  int line_max = 1024;
  char *riadok;
  int hladaj = 1;
  int pom = 0;   
  login = (char *) malloc(257*sizeof(char));
  heslo = (char *) malloc(257*sizeof(char));
  riadok = (char *) malloc((line_max+3)*sizeof(char));
  
  while (fgets(riadok, (line_max+1), file) != NULL)
  {
    pocet_riadkov++;
    len = strlen(riadok);
    if (len == line_max){
      printf("%s: riadok %d je dlhsi ako %d znakov\n", filename, pocet_riadkov, line_max);
      syslog(LOG_ERR, "%s: riadok %d je dlhsi ako %d znakov\n", filename, pocet_riadkov, line_max);
      //return 1;
    }
    else if(riadok[0] == '#')
    {
      // nasli sme odkomentovany riadok a neriesime ho
    }
    else if ((pom = sscanf(riadok, "%256s %256s", login, heslo)) == 2)
    {
      if (strlen(login) == 256)
      {
	printf("riadok %d suboru users.conf sa nepodarilo spracovat: login je dlhsi ako 255 znakov\n", pocet_riadkov);
	syslog(LOG_ERR, "riadok %d suboru users.conf sa nepodarilo spracovat: login je dlhsi ako 255 znakov\n", pocet_riadkov);
      }
      else if (strlen(heslo) == 256)
      {
	printf("riadok %d suboru users.conf sa nepodarilo spracovat: heslo je dlhsie ako 255 znakov\n", pocet_riadkov);
	syslog(LOG_ERR, "riadok %d suboru users.conf sa nepodarilo spracovat: heslo je dlhsie ako 255 znakov\n", pocet_riadkov);
      }
      else
      {
	
	pridaj_uzivatela(login, heslo);
      }
    }
    else if (pom == 1)
    {
      printf("%s: riadok %d suboru sa nepodarilo spracovat: ocakavany login a heslo\n", filename, pocet_riadkov);
      syslog(LOG_ERR, "%s: riadok %d suboru sa nepodarilo spracovat: ocakavany login a heslo\n", filename, pocet_riadkov);
    }
    else
    {
      //pravdepodobne prazdny riadok
    }
  }
  return 0;
}

/*
void pridaj_uzivatela(char *login, char *heslo)
- prida uzivatela do pola uzivatelia a zvysi pocet uzivatelov o 1;
- je to pomocna funkcia pre load_users_from_file() 
*/
void pridaj_uzivatela(char *login, char *heslo){
  int i = 0;
  
  if (pocet_uzivatelov == 0)
    uzivatelia = malloc(20*sizeof(UZIVATEL *));
  else if((pocet_uzivatelov%20) == 0)
  {
    uzivatelia = realloc(uzivatelia, pocet_uzivatelov + 20);
  }
  
  pocet_uzivatelov++;
  
  uzivatelia[(pocet_uzivatelov-1)] = (UZIVATEL *) malloc(sizeof(UZIVATEL));
  uzivatelia[(pocet_uzivatelov-1)]->login = (char *) malloc(256*sizeof(char));
  uzivatelia[(pocet_uzivatelov-1)]->heslo = (char *) malloc(256*sizeof(char));
  strncpy(uzivatelia[(pocet_uzivatelov-1)]->login, login, 256);
  strncpy(uzivatelia[(pocet_uzivatelov-1)]->heslo, heslo, 256);
  
}


/*
funkcia sa snazi nacitat volania z otvoreneho suboru danom na vstupe (MDEMONCONFPATH) kde su volania spravene napr takto
+421908687197	/bin/program program arg2 arg3
+421908687198	/usr/local/bin/program2 program2
0949123456	/bin/client client

funkcia cita cisla a k nim pridelene programy, ktore sa maju spustit po riadkoch
- riadok nesmie mat viac ako 1000 znakov

riadok - obsahuje cely aktualny riadok
najprv sa nacitajiu jednotlive riadky a ulozia sa do pola riadky[]
potom prejdeme riadky a z kazdeho riadku vyextrahujeme cislo a cesta pre program, 
ktory sa ma spustit spolu s argumentami ktorymi sa ma spustit (uvadza sa aj tzv nulty argument co je nazov programu - bez neho to nepojde)

*/
int load_volania_from_file(FILE **fvolania, char *filename){
  int i = 0;
  int j, len;
  
  int line_max = 1001;
  int pocet_riadkov = 0;
  char *riadok;
  int pocet_argumentov = 0;
  char *delimiters; 
  delimiters = strdup(" \t");
  char *cp;
  char *token;
  char **arguments;
  char *telefon;
  char *path; 
  pocet_volani = 0;
  volania = (VOLANIE **) malloc((pocet_volani+20)*sizeof(VOLANIE *));
  riadok = (char *) malloc((line_max+1)*sizeof(char));
  
  while (fgets(riadok, line_max, (*fvolania)) != NULL)
  {
    pocet_riadkov++;
    if (strlen(riadok) == line_max)
    {
      printf("riadok %d suboru %s je dlhsi ako %d znakov a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename, line_max);
      syslog(LOG_ERR, "riadok %d suboru %s je dlhsi ako %d znakov a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename, line_max);
    }
    else if (riadok[0] == '#')
    {
      // riadok sluziaci ako komentar
    }
    else
    {
      
      telefon = strtok(riadok, delimiters);
      
      if(telefon == NULL) 
      {
	// ak sa rovna NULL tak sme asi narazili na prazdny riadok a nema zmysel sa nim zapodievat
      }
      else if((path = strtok(NULL, delimiters)) == NULL)
      {
	printf("riadok %d suboru %s je chybny a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename);
	syslog(LOG_ERR, "riadok %d suboru %s je chybny a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename);
      }
      else
      {
	pocet_argumentov = 0;
	arguments = (char **) malloc(10*sizeof(char *));
	free(delimiters);
	delimiters = strdup(" \t\n");
	token = strtok(NULL, delimiters);
	while (token != NULL)
	{
	  pocet_argumentov++;
	
	  if ((pocet_argumentov%10)==0)
	  {
	    arguments = realloc(arguments, pocet_argumentov+10);
	  }
	  
	  arguments[pocet_argumentov-1] = strdup(token);
	  token = strtok(NULL, delimiters);
	}
	
	if (pocet_argumentov == 0)
	{
	  printf("riadok %d suboru %s je chybny a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename);
	  syslog(LOG_ERR, "riadok %d suboru %s je chybny a preto volanie z tohto riadka nebude akceptovane\n", pocet_riadkov, filename);
	}
	else
	{
	  pocet_volani++;
	  if ((pocet_volani%20) == 0)
	    volania = realloc(volania, pocet_volani+20);
	  j = pocet_volani -1;
	  volania[j] = (VOLANIE *) malloc(sizeof(VOLANIE));
	  
	  len = strlen(telefon);
	  volania[j]->telefon = (char *) malloc((len+1)*sizeof(char));
	  strncpy(volania[j]->telefon, telefon, len+1);
	
	  len = strlen(path);
	  volania[j]->path = (char *) malloc((len+1)*sizeof(char));
	  strncpy(volania[j]->path, path, len+1);
      
	  volania[j]->arguments = (char **) malloc((pocet_argumentov+1)*sizeof(char *));
	  for(i=0; i<pocet_argumentov; i++)
	  {
	    len = strlen(arguments[i]);
	    volania[j]->arguments[i] = (char *) malloc((len+1)*sizeof(char));
	    strncpy(volania[j]->arguments[i], arguments[i], len+1);
	  }
	}
	
      }
	
    }  
  }
  return 0;  
}

/*
nastav(char *command, char *hlaska)
- pomocna funkcia pre nastav_mobil()
- vysle prikaz co dostane na vstupe mobilu pomocou funkcie send_command_and_get_response a spat dostane response. 
  Ak send_command_and_get_response() vrati -1 mobil sa odpojil od MDemona a nastav konci s chybou -1. inak spracuje response a ak najde v odpovedi OK vrati 0. 
  Inak sa pokusi prikaz odoslat este raz a ak response ani teraz nebude mat OK tak vrati 1 akoze nastavenie sa nepodarilo. ak send_command_and_get_response vrati -1 vrati -1 (mobil sa odpojil) 
*/

int nastav(char *command, char *hlaska){
  char *response;
  int res = 0;
  
  
  res = send_command_and_get_response(command, &response);
  if (res == -1)
    return -1;
  else if(strstr(response, "OK") != NULL)
  {
    printf("%s OK\n", hlaska);
    syslog(LOG_INFO, "%s OK\n", hlaska);
    return 0;
  }
  else{
    res = send_command_and_get_response(command, &response);
    if (res == -1)
      return -1;
    else if(strstr(response, "OK") != NULL)
    {
      printf("%s OK\n", hlaska);
      syslog(LOG_INFO, "%s OK\n", hlaska);
      return 0;
    }
    else
    {
      printf("%s FAIL\n", hlaska);
      syslog(LOG_INFO, "%s FAIL\n", hlaska);
    }
    return 1;
  }
  
}


/*
nastav_mobil() 
  vysiela prikazi mobilu pomocu funkcie nastav - predlzenej ruky funkcie nastav. Funkci nastav posiela AT prikazy, 
  ktore sa maju poslat mobilu a ich nazov aky sa ma pouzit pri vystupe. Ak sa nastavenie nepodari ani na 2. pokus nastav vrati 1. 
  ak sa podari vrati 1 a v pripade, ze sa mobil odpojil -1. Pri -1 aj nastav_mobil skonci s -1 a main ukonci program
  Posielaju sa tieto AT prikazy (AT V1, AT+CLIP, AT+CMGF, AT+CHUP, )
*/
int nastav_mobil(void){
  printf("nastavujem mobil\n");
  syslog(LOG_INFO, "nastavujem mobil\n");
  char *response;
  int res = 0;
  
  if (nastav("AT V1\r", "AT V1") == -1)
    return -1;
  
  if ((res = nastav("AT+CLIP=1\r", "AT+CLIP")) == -1)
    return -1;
  else
  {
    if (res == 0)
      clip = 1;
    else
    {
      clip = 0;
      //mozno nejake dalsie upozornenie by bolo vhodne
    }
  }
  
  if ((res = nastav("AT+CMGF=1\r", "Text mode")) == -1)
    return -1;
  else
  {
    if (res == 0)
      text_mode = 1;
    else
    {
      text_mode = 0;
      if ((res = nastav("AT+CMGF=0\r", "PDU mode")) == -1)
	return -1;
      else if (res == 0)
	pdu_mode = 1;
      else
      {
	pdu_mode = 0;
	printf("Nemozno posielat sms\n");
	syslog(LOG_WARNING, "UNABLE TO SEND SMS\n");
      }
    }
  }
  
  if ((res = nastav("AT+CHUP\r", "AT+CHUP")) == -1)
    return -1;
  else
  {
    if (res == 0)
      chup = 1;
    else
    {
      chup = 0;
    }
  }
  
  printf("mobil nastaveny\n");
  syslog(LOG_INFO, "mobil nastaveny\n");
  return 0;
}

/*
vysle command mobilu a caka na uspokujujucu odpoved:
uspokujujuca odpoved obsahuje v sebe "OK", "ERROR" alebo ">" 
program pocuva mobil, kym nedostane uspokojujucu odpoved - TU MOZE ZAMRZNUT PROGRAM !
uspokojujuca odpoved sa ulozi v response. Uspokojujuca odpoved konci koncom riadka. 
Ak sprava od mobilu pokracuje za tymto koncom riadka, zavola sa na zvysok funkcia obsluz_mobil() so zvyskom spravy. ta spracuje zvysok spravy - podobne ako obsluz_mobil().
Po uspokojujucej odpovedi a pripadnom zavolani obsluz_mobil(), funkcia vracia 0 
ak z okolnosti vyplinie, ze mobil sa odpojil - poslal nula znakov - skonci s chybou -1.
Program ma este chybove stavy
 return 2 - nepodaril sa select
 return 4 - nepodarilo sa nacitat tolko znakov, kolko bolo ohlasenych ze mobil ma mat
*/
int send_command_and_get_response(char *command, char **response){
  fd_set input_fd_set;
  int max_fd;
  int len;
  int result;
  int nread;
  char *received;
  char *pom, *pom2;
  int i, counter;
  int flag = 1;
  int este_chceme_pocuvat = 1;
  char *poz, *cr;
  //printf("send_command_and_get_response(command=|%s|)\n", command);
 
  FD_ZERO(&input_fd_set);
  FD_SET(fd_mobile, &input_fd_set);
  max_fd = fd_mobile + 1;
  
  len = strlen(command);
  if (write(fd_mobile, command, len) != len)
  {
    perror("vyslanie commandu mobilu:");
    return 1;
  }
  
  fsync(fd_mobile);
  *response = malloc(2*sizeof(char));
  (*response)[0] = '\0';
  
  while(este_chceme_pocuvat)
  {
    result = select(max_fd, &input_fd_set, NULL, NULL, NULL);
 
    if (result <= 0)
    {
      perror("send_command_and_response:select");
      return 2;
    }   
    if (FD_ISSET(fd_mobile, &input_fd_set))
    {
      ioctl(fd_mobile, FIONREAD, &nread);
      if (nread == 0)
      {
	return -1; //mobil sa odpojil
      }
      pom = malloc((nread+3)*sizeof(char));
      len = read(fd_mobile, pom, nread);	
      if (len == 0)
      {
	printf("len = 0\n");
	return -1; // asi sa odpojil mobil
      }
      else if (len < nread)
      {
	printf("nepodarilo sa nacitat celu odpoved z mobilu\n nread=%d len=%d\n", nread, len);
	printf("nread=%d\n", len);
	pom[len] = '\0';
	printf("pom=|%s|\n", pom);
	*response = realloc(*response, (strlen(*response)+len+3)*sizeof(char));
        *response = strcat(*response, pom);
	return 4;
      }
      pom[nread] = '\0';
      *response = realloc(*response, (strlen(*response)+len+3)*sizeof(char));
      *response = strcat(*response, pom);

      if ((poz = strstr(*response, "OK")) != NULL)
      {
	if ((len = strlen(poz)) > 4)
	{
	  cr = strchr(poz, '\n');
	  if (cr != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else if ((cr = strchr(poz, '\r')) != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else
	  {
	    obsluz_mobil((poz+2*sizeof(char)));
	  }  
	}
	return 0;
      }
      else if ((poz = strstr(*response, "ERROR")) != NULL)
      {
	if ((len = strlen(poz)) > 7)
	{
	  cr = strchr(poz, '\n');
	  if (cr != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else if ((cr = strchr(poz, '\r')) != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else
	  {
	    obsluz_mobil((poz+5*sizeof(char)));
	  }  
	}
	return 0;
      }
      else if ((poz = strstr(*response, ">")) != NULL)
      {
	if ((len = strlen(poz)) > 3)
	{
	  cr = strchr(poz, '\n');
	  if (cr != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else if ((cr = strchr(poz, '\r')) != NULL)
	  {
	    obsluz_mobil((cr+sizeof(char)));
	  }
	  else
	  {
	    obsluz_mobil((poz+3*sizeof(char)));
	  }  
	}
	return 0;
      }
      else
      {
	este_chceme_pocuvat = 1;
      }
    }
    else
    {
      printf("nastala velmi divna situacia ktora vlastne nema ani sancu nastat\n");
      return 5;
    }
  }
}


/*
pokusi sa odoslat SMS s textom text na cislo number.
ak je text dlhsi ako 160 znakov vrati chybu 1
text nesmie obsahovat entre (konce riadkov) - lebo sa sms neodosle spravne, ale len po koniec riadku alebo vobec.
ak je nastaveny text_mode na 1, bude odosielat sms v textovom mode, inak zavola pomocnu funkciu send_PDUsms(char *number, *text), ktora pracuje rovnako ako send_sms 
 az nato, ze sa snazi odoslat sms v PDU mode
ak sme v textovom mode tak potom:
- posleme mobilu pomocou send_command_and_get_response(), prikaz AT+CMGS=<tel.n>\r , kde <tel.n> predstavuje number obdrzane vo volani funkcie
- cakame na response, ktory ma obsahovat ">" 
- odosleme text<CTRL-Z> pomocou send_command_and_get_response a cakame na response
- ak response obsahuje OK, povazujeme sms za uspesne odoslanu a send_sms vrati 0

- ak niekde vramci funkcie vysvitne, ze sa prerusilo spojenie s mobilom (napr send_command_and_get_response vrati -1), send_sms skonci s chybou a vrati -1.
*/
int send_sms(char *number, char *text){

  char *response;
  char *smscommand;
  int phonelength, smslength;
  int i, len, counter;
  int result;
  struct timeval timeout; // premenna urci kolko ma select cakat
  char *textcommand;

  if ((smslength = strlen(text))>160)
    return 1;
  
  if (text_mode)
  {
      phonelength = strlen(number);
      smscommand = (char *) malloc((strlen("AT+CMGS")+1+3+phonelength)*sizeof(char));
      smscommand[0]='A';
      smscommand[1]='T';
      smscommand[2]='+';
      smscommand[3]='C';
      smscommand[4]='M';
      smscommand[5]='G';
      smscommand[6]='S';
      smscommand[7]='=';
      smscommand[8]='"';
      counter = 0;
      for( i=9; i<(9+phonelength); i++){
	smscommand[i] = number[counter];
	counter++;
      }
      smscommand[9+phonelength] = '"';
      smscommand[10+phonelength] = '\r';  
      smscommand[11+phonelength] = '\n'; 
      smscommand[12+phonelength] = '\0';
    
    
    if ((result = send_command_and_get_response(smscommand, &response)) == 0)
    {
      for(i=0; i<strlen(response); i++)
      {
	if (response[i] == '\r')
	  response[i] = '\n';
      }
      
      textcommand = (char *) malloc(300);
      
      for(i=0; i<strlen(text); i++)
      {
	textcommand[i] = text[i];
      }
      textcommand[strlen(text)] = 26; // sem patri 26 27 spravi ESC :)
      textcommand[strlen(text)+1] = '\0';
      result = send_command_and_get_response(textcommand, &response);
      
      if (strstr(response, "OK") == NULL)
	return 3;
      else
	return 0;
      
    }
    
    if (result == -1)
      return -1; //mobil sa pravdepodobne odpojil
    else if (result == 2)
      return 3; //mobil nestihol odpovedat v casovom limite
  }
  else if (pdu_mode){
    result = send_PDUsms(number, text);
    return result;
  }

return 3;
  
}

/*
snazi sa odoslat sms v PDU mode s textom v text na cislo number
- najprv zisti ci mame naozaj nastaveny pdu_mode (pdu_mode = 1)
- potom overi ci number alebo text neodkazuju na NULL
- prevedie text na PDU text, ktory sa bude posielat mobilu, pricom zisti a kolkych septetov pozostava text zakodovany do GSM7 kodovania
- ak sprava pozostav z viac ako 160 septetov - skonci s chybou a vrati 1
- posleme mobilu pomocou send_command_and_get_response(), prikaz AT+CMGS=<no>\r , kde <no> predstavuje pocet oktetov, ktore ma sprava 
- cakame na response, ktory ma obsahovat ">" 
- odosleme zakodovanu spravu v PDU style ukoncenu <CTRL-Z> pomocou send_command_and_get_response a cakame na response
- ak response obsahuje OK, povazujeme sms za uspesne odoslanu a send_sms vrati 0

- ak niekde vramci funkcie vysvitne, ze sa prerusilo spojenie s mobilom (napr send_command_and_get_response vrati -1), send_sms skonci s chybou a vrati -1.
*/
int send_PDUsms(char *number, char *text){
  char *response;
  char *smscommand;
  char *pdutext;
  char *pdutextlength;
  char *pdunumber;
  int phonelength, smslength, pdutext_len;
  char *pdunumberlength;
  int i, len, counter;
  int result;
  int number_of_septets;
  struct timeval timeout; // premenna urci kolko ma select cakat
  char *textcommand;
  char c;
  
  if (!pdu_mode)
    return 3;
  if (text == NULL)
    return 1;
  else if ((smslength = strlen(text))>160)
    return 1; 
  if (number == NULL)
    return 1;
  else if((phonelength = strlen(number))>30)
    return 1;
  
  number_of_septets = asciText_to_PDUtext(text, &pdutext);
  pdutext_len = strlen(pdutext); 
  
  if (number_of_septets > 160)
    return 1;

  smscommand = (char *) malloc((strlen("AT+CMGS")+5)*sizeof(char));
  sprintf(smscommand, "AT+CMGS=%d\r\0", 12+(pdutext_len/2)+1);      
  if ((result = send_command_and_get_response(smscommand, &response)) == 0)
  {
    for(i=0; i<strlen(response); i++)
    {
      if (response[i] == '\r')
	response[i] = '\n';
    }
      
    textcommand = (char *) malloc((pdutext_len+36)*sizeof(char));
    pdutextlength = (char *) malloc((4)*sizeof(char));
    sprintf(pdutextlength, "%2X", number_of_septets);
    pdutextlength[0] = (pdutextlength[0] == ' '? '0': pdutextlength[0]);
    
    if (number[0] == '+'){
      pdunumberlength = (char *) malloc(3*sizeof(char));
      if ((phonelength-1)<16)
      {
	pdunumberlength[0] = '0';
	sprintf((pdunumberlength+1), "%1X", phonelength -1);
      }
      else
	sprintf(pdunumberlength, "%2X", phonelength-1);
      
      pdunumber = (char *) malloc((phonelength+3)*sizeof(char));
      pdunumber = strncpy(pdunumber, (number+1), phonelength);
      if (phonelength%2 == 0)
      {
	pdunumber[phonelength] = 'F';
	pdunumber[phonelength+1] = '\0';
	i = strlen(pdunumber)-1;
	while(i > 0){
	  c = pdunumber[i-1];
	  pdunumber[i-1] = pdunumber[i];
	  pdunumber[i] = c;
	  i -= 2;
	}
      }
      else
      {
	i = strlen(pdunumber)-1;
	while(i > 0){
	  c = pdunumber[i-1];
	  pdunumber[i-1] = pdunumber[i];
	  pdunumber[i] = c;
	  i -= 2;
	}
      }
      
      sprintf(textcommand, "000100%s91%s0000%s%s%c%s", pdunumberlength, pdunumber, pdutextlength, pdutext, 26, "\0"); 
    }
    
    result = send_command_and_get_response(textcommand, &response);
    
    if (result == -1)
      return -1; //mobil sa odpojil
    if (strstr(response, "OK") == NULL)
      return 3;
    else
      return 0;  
  }
  else if (result == -1)
     return -1; //mobil sa pravdepodobne odpojil
  else if (result == 2)
     return 3; //mobil nestihol odpovedat v casovom limite

return 3;
  
}

int zloz_telefon(){
 char *response;
  int result;
  
  if(chup){
    send_command_and_get_response("AT+CHUP\r\n", &response);
    if (strstr(response, "OK") == NULL)
	return 3;
      else
	return 0;
  }
  else
  {
    send_command_and_get_response("ATH\r\n", &response);
    if (strstr(response, "OK") == NULL)
	return 3;
      else
	return 0;
  }
}

int auth(char *login, char *heslo){
  int i;
  
  for(i=0; i<pocet_uzivatelov; i++){
    if ((strcmp(login, uzivatelia[i]->login) == 0) && (strcmp(heslo, uzivatelia[i]->heslo) == 0))
    {
      return 1;
    }
  }
  
  return 0;
}

int suspend(void){
  if (fd_mobile != -1)
  {
    close(fd_mobile);
    fd_mobile = -1;
  }
  suspended = 1;
  return 0; 
}

int resume(void){
  //printf("bol zavolany resume()\n");
  if (suspended == 0)
    return 0; // mobil nebol suspendovany takze nie je co resumovat avsak klient moze mat dobry pocit ze sa mu podaril RESUME
 
  
  fd_mobile = open( path, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK );
  if (fd_mobile == -1)
  {
    syslog(LOG_ERR, "open_port: Unable to open mobile device - %m"); /* nepodarilo sa otvorit port */
    return -1;
  }
   
  fcntl(fd_mobile, F_SETFL, 0);  /* nastavi descriptor aby po read vratil pocet vratenych bytov alebo 0 ak buffer pre input je prazdny - necaka na godota */
  suspended = 0;
  return nastav_mobil(); // -1 ak sa mobil odpojil 0 ak sa ho podarilo nastavit
}

/*
  vytvori soket na pocuvanie klientov a zviaze ho s adresou, ktoru dostal na vstupe. 
  file deskriptor ulozi do globalnej premennej fd_server_socket.
  V pripade ze ip="ALL" zviaze sa so vsetkymi ip adresami pocitaca(INADDR_ANY).
  V pripade neuspechu vrati -1.
*/
int sprav_server(char *ip, char *i_port){  
  int server_len;
  struct sockaddr_in server_address;
  int result;
  int port;
  
  if ((i_port != NULL) && (i_port[0] != '\0'))
    sscanf(i_port, "%d", &port);
  else
  {
    printf("sprav_server: nemozno otvorit dany port\n");
    syslog(LOG_ERR, "sprav_server: nemozno otvorit dany port\n");
    return -1;
  }
  fd_server_socket = socket(AF_INET, SOCK_STREAM, 0);
  if (fd_server_socket == -1)
  {
    perror("server_socket(socket())");
    syslog(LOG_ERR, "server_socket(socket()) - %m");
    return -1;    
  }
  if ((ip == NULL) || (ip[0] == '\0') || (strcmp(ip, "ALL") == 0))
    server_address.sin_addr.s_addr = htonl(INADDR_ANY);
  else
    server_address.sin_addr.s_addr = inet_addr(ip);
  server_address.sin_family = AF_INET;
  server_address.sin_port = htons(port);
  server_len = sizeof(server_address);
  
  result = bind(fd_server_socket, (struct sockaddr *) &server_address, server_len);
  if (result == -1)
  {
    perror("server_socket(bind())");
    syslog(LOG_ERR, "server_socket(bind()) - %m");
    return -1;    
  }
  
  return 0;
}


/*
  pocuva donekonecna mobil, klientov, server a akceptuje pripajajucich klientova a uklada ich pomocou pridaj_clienta do pola pripojenych klientov.
  ak pride od hocikoho 0 znakov - berie sa to akoze sa odpojil
  spravy od klienta riesi obsluz_klienta(), ktora na vstupe dostane kolko znakov si ma pytat (to zistuje ioctl()). 
   ak obsluz_klienta vrati -1, znamena to, ze sa mobil necakane odpojil od MDemona a vrati -1 - MDemon skonci
   ak obsluz_klienta vrati 1, znamena to ze klienta poslal CLOSE a rozhodol sa ukoncit MDemon, vtedy pocuvaj vrati 0 a MDemon skonci
  spravy od mobilu ak nie je odpojeny (suspended = 0) obsluhuje obsluz_mobil(), ktory na vstupe dostane kolko znakov si ma pytat (to zistuje ioctl()).
    ak obsluz_mobil vrati -1, , znamena to, ze sa mobil necakane odpojil od MDemona a vrati -1 - MDemon skonci.

*/
int pocuvaj(void){
  struct sockaddr_in client_address;
  int client_len = sizeof(client_address);
  fd_set input_fd_set;
  int max_fd;
  int fd_client_socket;
  int fd;
  int este_chceme_pocuvat = 1;
  int nread;
  int result;
  int i, j;
  char *sprava_od_clienta;
  char *sprava_od_mobile;
  int pocet_precitanych_znakov;
  
  listen(fd_server_socket, 5);
  printf("server pocuva(listen)\n");
  syslog(LOG_INFO, "server pocuva(listen)\n");
  
  FD_ZERO(&input_fd_set);
  FD_SET(fd_mobile, &input_fd_set);
  FD_SET(fd_server_socket, &input_fd_set);
  max_fd = (fd_mobile > fd_server_socket ? fd_mobile : fd_server_socket);
  
  while(este_chceme_pocuvat){
    result = select((max_fd+1), &input_fd_set, NULL, NULL, NULL);
    if (result < 0)
      return -1;
    if ((!suspended) && FD_ISSET(fd_mobile, &input_fd_set))
    {
      ioctl(fd_mobile, FIONREAD, &nread); 
      if (nread == 0)
      {
	close(fd_mobile);
	fd_mobile = -1;
	//printf("demon stratil necakane spojenie s mobilom a preto konci\n");
	return -1;
      }
      else
      {  
	sprava_od_mobile = (char *) malloc((nread+3)*sizeof(char));
	pocet_precitanych_znakov = read(fd_mobile, sprava_od_mobile , nread);
	if (pocet_precitanych_znakov != nread)
	{
	  syslog(LOG_NOTICE, "precital som %d znakov namiesto %d\n", pocet_precitanych_znakov, nread);
	  sprava_od_mobile[pocet_precitanych_znakov] = '\0';
	  syslog(LOG_NOTICE, "precitane bolo:%s\n", sprava_od_mobile);
	  syslog(LOG_ERR, "stratilo sa spojenie s mobilom a mdemon bol vypnuty\n");
	  return -1;
	}
	sprava_od_mobile[nread] = '\0';
	obsluz_mobil(sprava_od_mobile);
	
      }
    }
    if (FD_ISSET(fd_server_socket, &input_fd_set))
    {
      fd_client_socket = accept(fd_server_socket, (struct sockaddr *)&client_address, &client_len);
      max_fd = ( (fd_client_socket > max_fd ? fd_client_socket : max_fd ) );
      pridaj_clienta(fd_client_socket);
      //printf("prijal som klienta\n");
      syslog(LOG_INFO, "prijal som klienta fd=%d\n", fd_client_socket);
    }
    for(i=0; i<pocet_clientov; i++)
    {
      if (FD_ISSET(clienti[i]->fd, &input_fd_set))
      {
	fd_client_socket = clienti[i]->fd;
	ioctl(fd_client_socket, FIONREAD, &nread);
	  
	if (nread == 0)
	{
	  close(fd_client_socket);
	  syslog(LOG_INFO, "clientn(fd=%d) sa odpojil\n", fd_client_socket);
	  odober_clienta(fd_client_socket);
	  if (fd_suspender == fd_client_socket)
	  {
	    fd_suspender = -1;
	  }
	  i--;
	}
	else
	{
	  sprava_od_clienta = (char *) malloc((nread+3)*sizeof(char));
	  pocet_precitanych_znakov = read(fd_client_socket, sprava_od_clienta , nread);
	  //syslog(LOG_INFO, "pocet_precitanych_znakov=%d", pocet_precitanych_znakov);
	  if (pocet_precitanych_znakov != nread)
	  {
	    //write(fd, "400\n", 3); //nepodarilo sa nacitat vstup a vnimame to ze sa client odpojil
	    close(fd_client_socket);
	    odober_clienta(fd_client_socket);
	    i--;
	    syslog(LOG_INFO, "client(fd=%d) sa odpojil\n", fd_client_socket);
	  }
	  else
	  {
	    sprava_od_clienta[nread] = '\0';
	    /*
	      zisti co chce klient a obsluz jeho poziadavku
	    */  
	    //printf("dostal som nieco od klienta a idem ho obsluzit\n");
	    if ((result = obsluz_clienta(sprava_od_clienta, fd_client_socket)) == -1)
	    {
	      //mobil sa asi odpojil
	      //printf("demon stratil necakane spojenie s mobilom a preto konci\n");
	      close(fd_mobile);
	      fd_mobile = -1;
	      return -1;
	    }
	    else if (result == 1)
	    {
	      close(fd_client_socket);
	      odober_clienta(fd_client_socket);
	      i--;
	      syslog(LOG_INFO, "client(fd=%d) sa odpojil\n", fd_client_socket);
	    }
	    else if (result == 5)
	    {
	      syslog(LOG_INFO, "client(fd=%d) poslal CLOSE - MDemon konci\n", fd_client_socket);
	      return 0;
	    }
	  }
	    
	}
      }
    }
    FD_ZERO(&input_fd_set);
    
    if (!suspended)
      FD_SET(fd_mobile, &input_fd_set);
    if (fd_mobile > max_fd)
      max_fd = fd_mobile;
    
    FD_SET(fd_server_socket, &input_fd_set);
    max_fd = (max_fd < fd_server_socket ? fd_server_socket : max_fd);
    for(i=0; i<pocet_clientov; i++)
    {
      FD_SET(clienti[i]->fd, &input_fd_set);
      if (clienti[i]->fd > max_fd)
	max_fd = clienti[i]->fd;
    }    
  }
}

/*
  Pridaj_clienta(fd), odober_clienta(fd) - pridavaju a odoberaju klientov z pola pripojenych klientov, pricom aktualizuju informaciu o pocte klientov
  daj_clienta - vytiahne klienta zo zoznamu klientov a odkaz na neho vrati v premmennej client. (nemaze klienta z databazy len poskytuje nan odkaz)
*/
int pridaj_clienta(int fd){
 
 if (pocet_clientov == 0)
   clienti = (CLIENT **) malloc(20*sizeof(CLIENT *));
 else if ((pocet_clientov%20) == 0)
   clienti = (CLIENT **) realloc( clienti, (pocet_clientov+20)*sizeof(CLIENT *));
 
 clienti[pocet_clientov] = malloc(sizeof(CLIENT));
 clienti[pocet_clientov]->fd = fd;
 clienti[pocet_clientov]->authorized = 0;
 clienti[pocet_clientov]->buffer = malloc(sizeof(char));
 clienti[pocet_clientov]->buffer[0]='\0';
 pocet_clientov++;
}

int odober_clienta(int fd){
  int i;
  for(i=0; i<pocet_clientov; i++){
    if (clienti[i]->fd == fd)
    {
      clienti[i]->fd = clienti[pocet_clientov-1]->fd;
      clienti[i]->authorized = clienti[pocet_clientov-1]->authorized;
      free(clienti[i]->buffer);
      clienti[i]->buffer = strdup(clienti[pocet_clientov-1]->buffer);
      free(clienti[pocet_clientov-1]);
      pocet_clientov--;
      return 0;
    }
  }
  return -1;
}

int daj_clienta(int fd, CLIENT **client){
  int i;
  for(i=0; i<pocet_clientov; i++){
    if (clienti[i]->fd == fd)
    {
      *client = (clienti[i]);
      return 0;
    }
  }
  return 1;
}


/*
  vyprazdni buffer, ktory dostane na vstupe - vyuzivany pre buffre klientov
*/
void resetuj_buffer(char **buffer){
  free(*buffer);
  *buffer = malloc(sizeof(char));
  (*buffer)[0]='\0';
}

/*
  prida co do do daneho buffru - vyuzivany pre buffre klientov 
*/
void pridaj_do_buffru(char **buffer, char *co){
  *buffer = realloc(*buffer, (strlen(*buffer)+strlen(co)+5)*sizeof(char));
  *buffer = strcat(*buffer, co);
}

/*
  vrati 1 ak je klient autorizovany
        0 ak nie je
*/
int autorizovany_client(int fd){
  int i;
  for(i=0; i<pocet_clientov; i++){
    if ((clienti[i]->fd == fd) && (clienti[i]->authorized))
    {
      return 1;
    }
  }
  return 0;
}


/*
int obsluz_clienta(int nread, int fd)
  - funkcia sluziaca na vybavovanie poziadaviek od klientskych aplikacii
  - na vstupe dostava spravu od klienta a file deskriptor klienta. Na zaklade filedescriptoru si nacita klienta z databazy pripojenych klientov - ak sa enpodari nacitat klient,
      funkcia vrati 2.
  - sprava od klienta sa prida do buffru klienta - sluzi na skladanie nekompletnych sprav od klienta 
  - jeden cely prikaz od klienta je ukonceny znakom '\n' - vsetko za '\n' sa povazuje za dalsiu spravu od klienta a po spracovani prveho celeho prikazu sa na zvysok zavola
    opat obsluz_clienta() s fd clienta a zvyskom spravy. vysledok z volaneho obsluz_clienta vrati aj volajuci obsluz_clienta.
  - ak sprava od klienta nie je ukoncena '\n', bude pridana do buffru klienta a obsluz_klienta skonci s 0;
  - prikazy spracovavane programom:
    AUTH login heslo\n  - sluzi na autorizaciu(login heslo su parametre)
    SUSPEND\n - sluzi na odpojenie mdemona od mobilu
    RESUME\n - sluzi na znovupripojenie mdemona k mobilu
    SENDSMS\n tel text - sluzi na odoslanie sms - text nesmie byt dlhsi ako 160 znakov v GSM 7 abecede
    CLOSE\n - sluzi na ukoncenie programu MDemon
  - ine spravy budu zamietnute a klient dostane spravu ze ich mdemon nevie spracovat
  - na vykonanie vsetkych prikazov okrem AUTH musi byt klient autorizovany. SUSPEND a RESUME sa vykona ak MDemon nebol predtym odpojeny inim stale pripojenym klientom.
  - v pripade, ze autorizovany klient poslal CLOSE, funkcia vrati 5, co signalizuje ze mdemon sa ma ukoncit
  Navratove hodnoty:
    0 - skoncil uspesne
    1 - klient sa odpojil od MDemon
    2 - nepodarilo sa nacitat klienta z databazy pripojenych klientov
    5 - autorizovany klient poslal CLOSE
*/
int obsluz_clienta(char *sprava_od_clienta, int fd){
  char *pom;
  char *cp, *prikaz;
  int pocet_precitanych_znakov;
  int pocet;
  CLIENT *client;
  char *za_lf = NULL;
  char *lf;
  int res;
  
  
  if (daj_clienta(fd, &client) != 0)
    return 2;
   
  pridaj_do_buffru(&(client->buffer), sprava_od_clienta);
  cp = strdup(client->buffer);
  if ((lf = strchr(cp, '\n')) == NULL)
  {
    return 0;
  }
  else if(strlen(lf) > 1)
  {
    za_lf = lf+1;
    resetuj_buffer(&(client->buffer));
  }
  else
  {
    za_lf = NULL;
    resetuj_buffer(&(client->buffer));
  }
  
  prikaz = strtok(cp, " \t\n\r");
  if (strcmp(prikaz, "AUTH") == 0)
  {
    char *login, *heslo;
    login = strtok(NULL, " \t");
    heslo = strtok(NULL, " \n\t\r");
    //printf("login:|%s|, heslo:|%s|", login, heslo);
    if ((login != NULL) && (heslo != NULL))
    {
      if (auth(login, heslo) == 1)
      {
	client->authorized = 1;
	write(fd, "200:AUTH succeeded\n", strlen("200:AUTH succeeded\n")); // clienta sa podarilo autorizovat
	syslog(LOG_INFO, "clienta(login=%s fd=%d) sa podarilo autorizovat\n", login, client->fd);
      }
      else
      {
	client->authorized = 0;
	write(fd, "406:AUTH failed - zly login alebo heslo\n", strlen("406:AUTH failed - zly login alebo heslo\n")); // clienta sa nepodarilo autorizovat
	syslog(LOG_INFO, "clienta(login=%s fd=%d) sa nepodarilo autorizovat - zly login alebo heslo\n", login, client->fd);
	return 0;
      }
    }
    else
    {
      write(fd, "400:AUTH failed - zly format vstupu<LF>\n", strlen("400:AUTH failed - zly format vstupu<LF>\n")); // clienta sa nepodarilo autorizovat poslal zly format vstupu
      syslog(LOG_INFO, "clienta(fd=%d) sa nepodarilo autorizovat - chybny format vstupu\n", client->fd);
      return 0;
    }
  }
  else if(strcmp(prikaz, "SUSPEND") == 0)
  {
    if (!client->authorized)
    {
      write(fd, "401:SUSPEND failed - musite sa najprv autorizovat\n", strlen("401:SUSPEND failed - musite sa najprv autorizovat\n")); 
      syslog(LOG_INFO, "neatorizovany(fd=%d) client sa pokusil o SUSPEND ale bol zamietnuty(401)\n", client->fd);
    }
    else
    {
      if (!suspended)
      {
	res = suspend();
	if (res != 0)
	{
	  write(fd, "500:SUSPEND failed - neznama chyba\n", strlen("500:SUSPEND failed - neznama chyba\n"));
	  syslog(LOG_INFO, "500:SUSPEND failed - neznama chyba(fd=%d))\n", client->fd);
	}
	else
	{
	  fd_suspender = fd;
	  write(fd, "200:SUSPEND succeeded\n", strlen("200:SUSPEND succeeded\n"));
	  syslog(LOG_INFO, "SUSPENDED(mdemon bol odpojeny od mobilu clientom(fd=%d))\n", client->fd);
	}
      }
      else if((fd_suspender == -1) || (fd_suspender == fd))
      {
	fd_suspender = fd;
	write(fd, "200:SUSPEND succeeded\n", strlen("200:SUSPEND succeeded\n"));
        syslog(LOG_INFO, "SUSPENDED(mdemon bol odpojeny od mobilu clientom(fd=%d))\n", client->fd);
      }
      else{
	write(fd, "403:SUSPEND failed - MDemon bol suspendovany inym klientom\n", strlen("403:SUSPEND failed - MDemon bol suspendovany inym klientom\n"));
        syslog(LOG_INFO, "403:SUSPEND failed - MDemon bol suspendovany inym klientom(fd=%d))\n", client->fd);
      }
      
    }
  }
  else if(strcmp(prikaz, "RESUME") == 0)
  {
    if (!client->authorized)
    {
      write(fd, "401:RESUME failed - musite sa najprv autorizovat\n", strlen("401:RESUME failed - musite sa najprv autorizovat\n")); 
      syslog(LOG_INFO, "neatorizovany(fd=%d) client sa pokusil o RESUME ale bol zamietnuty(401)\n", client->fd);
    }
    else
    {
      if (suspended && ((fd_suspender == fd) || (fd_suspender == -1)))
      {
	if (resume()!=0)
	{
	  write(fd, "500:RESUME failed - neznama chyba\n", 3);
	  syslog(LOG_ERR, "nepodarilo sa resume() - neznama chyba\n");
	}
	else
	{
	  write(fd, "200:RESUME succeeded\n", strlen("200:RESUME succeeded\n"));
	  syslog(LOG_INFO, "RESUMED(mdemon bol opatovne pripojeny k mobilu clientom(fd=%d))\n", client->fd);
	}
      }
      else if (suspended)
      {
	write(fd, "403:RESUME failed - MDemon bol suspendovany inym klientom, ktory je stale aktivny\n", strlen("403:RESUME failed - MDemon bol suspendovany inym klientom, ktory je stale aktivny\n"));
	syslog(LOG_INFO, "clientovi(fd=%d) sa nepodarilo RESUME pretoze demon bol suspendovany clientom(fd=%d)\n", client->fd, fd_suspender);
      }
      else
      {
	write(fd, "200:RESUME succeeded\n", strlen("200:RESUME succeeded\n"));
      }
    }
  }
  else if(strcmp(prikaz, "CLOSE") == 0)
  {
    if (!client->authorized)
    {
      write(fd, "401:CLOSE failed - musite sa najprv autorizovat\n", strlen("401:CLOSE failed - musite sa najprv autorizovat\n")); 
      syslog(LOG_INFO, "neatorizovany(fd=%d) client sa pokusil o CLOSE ale bol zamietnuty(401)\n", client->fd);
      return 0;
    } 
    else{
      write(fd, "200:CLOSE succeeded\n", strlen("200:CLOSE succeeded\n")); 
      syslog(LOG_INFO, "Klient(fd=%d) poslal CLOSE", fd);
      return 5;
    }
  }
  else if(strcmp(prikaz, "SENDSMS") == 0)
  {
    char *tel, *text;
    int result;
    
    tel = strtok(NULL, " \t\r\n");
    text = strtok(NULL, "");
    
    if (!client->authorized)
    {
      write(fd, "401:SENDSMS failed - musite sa najprv autorizovat\n", strlen("401:SENDSMS failed - musite sa najprv autorizovat\n")); 
      syslog(LOG_INFO, "neatorizovany(fd=%d) client sa pokusil o SENDSMS ale bol zamietnuty(401)\n", client->fd);
      return 0;
    } 
    if (text == NULL)
    {
      text = (char *) malloc(5);
      text[0] = '\0';
    }
    if (tel == NULL)
    {
       write(fd, "400:SENDSMS failed - zly format vstupu\n", strlen("400:SENDSMS failed - zly format vstupu\n")); 
      syslog(LOG_INFO, "clientovi(fd=%d) sa nepodarilo SENDSMS - chybny format vstupu\n", client->fd);
      //return 0;      
    }
    else if (suspended)
    {
      write(fd, "403:SENDSMS failed - MDemon je suspendovany\n", strlen("403:SENDSMS failed - MDemon je suspendovany\n")); 
      syslog(LOG_INFO, "clientovi(fd=%d) sa nepodarilo SENDSMS - MDemon je suspendovany\n", client->fd);
    }
    else
    {
      result = strlen(text);
      text[result-1] = '\0';
      
      //printf("send_sms:|%s| |%s|\n", tel, text);
      result = send_sms(tel, text);
      if (result == 0)
      {
	write(fd, "200:SENDSMS succeeded\n", strlen("200:SENDSMS succeeded\n")); 
	syslog(LOG_INFO, "client(fd=%d) uspesne odoslal SMS(%s, %s)\n", client->fd, tel, text);
      }
      else if (result == 3)
      {
	write(fd, "500:SENDSMS failed - neznama chyba\n", strlen("500:SENDSMS failed - neznama chyba\n")); 
	syslog(LOG_INFO, "clientovi(fd=%d) sa nepodarilo odoslat SMS(%s, %s)\n", client->fd, tel, text);
      }
      else if (result == 1)
      {
	write(fd, "402:SENDSMS failed - zly format vstupu: sms nesmie byt dlhsia ako 160 znakov v gsm7 formate\n", 
	strlen("402:SENDSMS failed - zly format vstupu: sms nesmie byt dlhsia ako 160 znakov v gsm7 formate\n")); 
	syslog(LOG_INFO, "SENDSMS - neplatny format vstupu - client(fd=%d) chcel pravdepodobne poslat sms dlhsiu ako 160 znakov\n", client->fd);
      }
      else if (result == -1)
      {
	return -1; //mobil sa pravdepodobne odpojil
      }
    }
  }
  else
  {
    write(fd, "400:neviem spracovat danu spravu\n", strlen("400:neviem spracovat danu spravu\n")); //klient poslal blbost
    syslog(LOG_ERR, "client(fd=%d) poslal blbost:%s\n", client->fd, cp);
  }
  if (za_lf != NULL)
  {
    return obsluz_clienta(za_lf, fd);
  }
  return 0;
}


/*
  funkcie spravujuce buffer sprav od mobilu
*/
void pridaj_do_mbuffru(char *co){
  mbuffer = realloc( mbuffer, (strlen(mbuffer)+strlen(co)+3)*sizeof(char));
  mbuffer = strcat(mbuffer, co);
}

void resetuj_mbuffer(){
  free(mbuffer);
  mbuffer = (char *) malloc(sizeof(char));
  mbuffer[0] = '\0';
}


/*
int obsluz_mobil(char *sprava_od_mobile)
  - sluzi na vybavovanie sprav od mobilu - konkretne pocuva ci niekto nevola
  - ak sprava obsahuje RING a je zapnuty CLIP, zisti ci ma celu spravu od mobilu minimalne ci ma cele cislo(cislo je poslane v zatvorkach) a ak ano, 
     tak zavola funkciu vybav_volanie s vyextrahovanym telefonnym cislom zo spravy. (tato funkcia zlozi telefon a zisti ci je tel cislo v zozname, 
       ak ano spusti program pre dane cislo v kopii procesu MDemon)
  - ak sprava obsahuje RING a nie je zapnuty CLIP, zavola vybav_volanie s prazdnim stringom - da sa nastavit aby sa spustil nejaky program pre hocijake cislo co zavola.
  - vracia len 0

*/
int obsluz_mobil(char *sprava_od_mobile){
  char *pom, *cr, *lf;
  char *telefon;
  char *uvozovky;
  int pocet_precitanych_znakov;
  int result;
  char *response;
  
  //printf("obsluhujem mobil nread=%d\n", nread);
  
  pridaj_do_mbuffru(sprava_od_mobile);
  if ((strstr(mbuffer, "RING") != NULL) && clip)
  {
    //printf("niekto vola\n");
    if ( (strstr(mbuffer, "CLIP") != NULL) &&
         ((uvozovky = strchr(mbuffer, '\"')) != NULL) &&
         ( (pom = strchr((uvozovky+sizeof(char)), '\"')) != NULL) &&
         (((lf = strchr(uvozovky, '\n')) != NULL) || ((cr = strchr(uvozovky, '\r')) != NULL)) )
    {
      telefon = malloc((((int)pom-(int)uvozovky)+3*sizeof(char)));
      telefon[0]= '\0';
      telefon = strncpy(telefon, (uvozovky+sizeof(char)), ((pom-uvozovky-1)/sizeof(char)));
      syslog(LOG_INFO, "vola:%s\n", telefon);
      if (lf != NULL)
      {
	if (strlen(lf) > 1)
	{
	  resetuj_mbuffer();
	  obsluz_mobil((lf+1));
	}
	else
	  resetuj_mbuffer();
	}
      else if (strlen(cr) > 1)
      {
	resetuj_mbuffer();
	obsluz_mobil((cr+1));
      }
      else
	resetuj_mbuffer();
      
      result = vybav_volanie(telefon);
      syslog(LOG_INFO, "volanie vybavene:%d\n", result);
    }
    else
    {
      //sprava od mobilu nebola cela
    }
  }
  else if(((pom = strstr(mbuffer, "RING")) != NULL) && (clip == 0))
  {
    lf = strchr(pom, '\n');
    if (lf != NULL)
    {
      if (strlen(lf) > 1)
      {
	resetuj_mbuffer();
	obsluz_mobil((lf+1));
      }
      else
	resetuj_mbuffer();
    }
    else if ((cr = strchr(pom, '\r')) != NULL)
    {
      if (strlen(cr) > 1)
      {
	resetuj_mbuffer();
	obsluz_mobil((cr+1));
      }
      else
	resetuj_mbuffer();
    }
    result = vybav_volanie("");
    syslog(LOG_INFO, "volanie vybavene:%d\n", result);
  }
  else
  {
    //printf("sprava od mobile:%s\n", mbuffer);
  }
  //nie sme schopny zistit ci volajuci prestal vyzvanat
  
  return 0;
}

int vybav_volanie(char *tel){
  int i;
  int kde = -1;
  int dieta;
  char *cislo;
  char *skratene_cislo;
  char *response;
  int len;
  int result;
  
  zloz_telefon();
  
  len = strlen(tel);
  cislo = (char *) malloc((len+3)*sizeof(char));
  skratene_cislo = (char *) malloc((len+3)*sizeof(char));
  strncpy(cislo, tel, (len+1));
  
  if (len == 0)
  {
    free(cislo);
    cislo = "ALL";    
  }
  else if (cislo[0] == '+')
  {
    for(i=0; i<len; i++)
    {
      cislo[i] = cislo[i+1];
    }
    len--;
  }
  
  if (len >= 11)
  {
    for(i=0; i<(len-2); i++)
    {
      skratene_cislo[i] = cislo[i+3];
    }
  }
  else if (cislo[0] == '0')
  {
    for(i=0; i<(len); i++)
    {
      cislo[i] = cislo[i+1];
    }
  }
  else
  {
    strcpy(skratene_cislo, cislo);
  }
  
  //prezrieme ci nenajdeme v telefonoch cislo co sme dostali na vstupe
  for (i=0; i<pocet_volani; i++)
  {
    if (strstr(volania[i]->telefon, cislo) != NULL)
    {
      kde = i;
    }    
  }
  
  //prezrieme ci nenajdeme v telefonoch cislo bez medzinarodnej predvolby co sme dostali na vstupe
  if (kde == -1)
  {
    for (i=0; i<pocet_volani; i++)
    {
      if (strstr(volania[i]->telefon, skratene_cislo) != NULL)
      {
	kde = i;
      }    
    }
  }
  
  if (kde >= 0)
  {
      dieta = fork();
      if(dieta == -1)
      {
	perror("vybav_volanie:fork()");
	return -1;
      }
      else if (dieta == 0)
      {
	syslog(LOG_INFO, "mdemon spusta program:|%s|", volania[kde]->path);
	execv(volania[kde]->path, volania[kde]->arguments);
	//return -1; //neviem ci ma zmysel
      }
      else 
	return dieta;
  }
  return 0;
}

